#include "Sesion.h"
#include "log.h"
#include <stdlib.h>
#include <vector>
#include <stdarg.h>
#include <sys/wait.h>
#include "mensajes/Mensaje.h"
#include "Cola.h"
#include "ListaCompartida.h"
#include "ListaUsuarios.h"

#define EXIT_ERROR_PARAMETROS 1
#define EXIT_ERROR_SESION     2
#define EXIT_ERROR_FORK       3
#define EXIT_ERROR_EXEC       4

void listarConversaciones(Sesion &sesion){
   std::vector<long> lista = sesion.listarTodasLasConversaciones();

    if(lista.size() == 0)
	log(stdout, "No hay conversaciones.\n");
    for (unsigned int i = 0; i < lista.size(); ++i){
	log(stdout, "Id Conversacion: %ld\n", lista[i]);
    }
}

unsigned lanzarProcesosHijos(const char* nombre, long idUsuario, long idConversacion){
    char usuario[10];
    char conversacion[10];

    sprintf(usuario, "%ld", idUsuario);
    sprintf(conversacion, "%ld", idConversacion);
    log(stdout, "Lanzando proceso %s....\n", nombre);
    
    unsigned childpid=fork();
    if(childpid < 0){
	log(stdout, "Error en el fork proceso %s\n", nombre);
	exit(EXIT_ERROR_FORK);
    }
    if(childpid == 0){
	execlp(nombre, nombre, (const char*) usuario, (const char*) conversacion, (char*) NULL);
	log(stdout, "Error al lanzar %s\n", nombre);
	exit(EXIT_ERROR_EXEC);
    }
    return childpid;
}

long preguntarNumero(){
    log(stdout, "Elija el numero de conversacion (0 para crear una nueva).\n");
    char buffer[50];
    fgets(buffer, 50, stdin);
    return atoi(buffer);
}

void resetearRecursosCompartidos(){
    ListaCompartida<long> conversacionesActuales(FTOK_PATH,LISTA_COMPARTIDA_CONVERSACIONES);
    conversacionesActuales.clear();
    
    Cola::destruir(FTOK_PATH, ID_COLA_INBOX);
    Cola::destruir(FTOK_PATH, ID_COLA_OUTBOX);
    ListaUsuarios l;
    l.clear();
}

int main(int argc, char *argv[]){

    log("Tamanios de mensaje: Mensaje: %d, MensajeSYNC: %d, MensajeTXT: %d.\n", sizeof(Mensaje), sizeof(MensajeSYNC), sizeof(MensajeTXT));
    log("int:%d, long:%d\n", sizeof(int), sizeof(long));

    if(argc < 3) {
	log(stdout, "%s <numero usuario> <control_host>\n", argv[0]);
	exit(EXIT_ERROR_PARAMETROS);
    }

    long numeroUsuario = atol(argv[1]);
    char* host = argv[2];

    resetearRecursosCompartidos();

    Sesion sesion;

    if(!sesion.iniciar(numeroUsuario, host)){
	log(stdout, "No se puede iniciar sesion.\n");
	exit(EXIT_ERROR_SESION);
    }

    //Lanzo el server receptor
    if(fork() == 0){
	execlp("./receptor_server", "receptor_server", NULL);
    }

    listarConversaciones(sesion);

    long id = preguntarNumero();

    if(id == 0){
    	id = sesion.crearConversacion();
    	log(stdout, "Creada nueva conversacion %ld.\n", id);
    }

    if(sesion.unirseAConversacion(id)){

     	log(stdout, "Lanzo subprocesos con usuario %ld y conversacion %ld\n", numeroUsuario, id);

	char usuario[20];
	char conversacion[20];
	
	sprintf(usuario, "%ld", numeroUsuario);
	sprintf(conversacion, "%ld", id);

	int pid1 = lanzarProcesosHijos("editor", numeroUsuario, id);
     	lanzarProcesosHijos("presentador", numeroUsuario, id);

     	waitid(P_PID, pid1, NULL, WEXITED);

     	sesion.cerrarConversacion(id);

     	listarConversaciones(sesion);
    }
    
    sesion.cerrar();
    
    return 0;
}
